﻿#ifdef _WIN32
#pragma execution_character_set("utf-8")
#endif

#include "tbworker.h"
#include <QDate>
#include <QTime>
#include <QDebug>
#include <QJsonParseError>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QVector>
#include <QList>
#include <QThread>
#include <QCryptographicHash>
#include <iostream>
#include <QDir>
#include <QNetworkReply>
#include <QEventLoop>
#include <QNetworkCookieJar>
#include <QNetworkCookie>
#include <QMap>
#include <curl/curl.h>

#ifdef _WIN32
#include <windows.h>
#pragma comment(lib, "winmm.lib")
#else
#include <QMediaPlayer>
#endif

/*
将相关链接和用户名、密码替换为自己的，重新编译即可
*/
const static QString JHPT_VER_CODE_URL = "";
const static QString JHPT_GET_DATA_URL = "";
const static QString JHPT_LOGIN_URL = "";
const static QString JHPT_A13_DATA_URL = "";
const static QString JHPT_NOTE_URL = "";
const static QString JHPT_ASK_URL = "";

const static QString USER_NAME = "";
const static QString PASS_WOERD = "";


tbWorker::tbWorker(QObject *parent) : QObject(parent)
{    
    m_busidate = QSharedPointer<BusiDate>(new BusiDate);
    m_request_manager = new QNetworkAccessManager;
}

tbWorker::~tbWorker()
{
    m_request_manager->deleteLater();
    m_request_manager = nullptr;
}

//获取核实反馈数据
void tbWorker::get_zjjk_data()
{

    //登录
    m_login();

    //获取请求POST数据
    QString startDate = QDate::currentDate().addDays(-30).toString("yyyyMMdd");    
    QString endDate = m_busidate->getEndDate();

    //整理请求POST数据
    QString userInfo = QString("startDate=%1&endDate=%2&userId=%3&orgId=%4&orgType=%5")
            .arg(startDate,endDate,"7204","10440000","3");
    std::string post_data = userInfo.toStdString();

    //清除结果数据
    zjjk_data.clear();

#ifndef _WIN32
    //通过CURL请求数据
    struct curl_slist * headers = NULL;
    headers = curl_slist_append(headers,"Accept:application/json;charset=utf-8");
    headers = curl_slist_append(headers,"Content-Type:application/x-www-form-urlencoded;charset=UTF-8");
    headers = curl_slist_append(headers,"User-Agent:Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0");
    CURL* curl = curl_easy_init();
    curl_easy_setopt(curl,CURLOPT_URL,"http://www.sipf.com.cn/jhpt/tDataOverview/getGridForQg.action");
    curl_easy_setopt(curl,CURLOPT_POST,1L);
    curl_easy_setopt(curl,CURLOPT_POSTFIELDS,post_data.c_str());
    curl_easy_setopt(curl,CURLOPT_COOKIEFILE,"cookies");
    curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers);
    curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,request_callback);
    curl_easy_setopt(curl,CURLOPT_WRITEDATA,&zjjk_data);

    CURLcode res = curl_easy_perform(curl);
    if (res != CURLE_OK)
    {
        emit send_log(QString("login fail: %1\n").arg(curl_easy_strerror(res)));
    }
    curl_easy_cleanup(curl);
    zjjk_data = zjjk_data.trimmed();
    emit send_log(zjjk_data);
    if(!zjjk_data.endsWith(']') && zjjk_data.contains(']'))
    {
        int index = zjjk_data.indexOf(']');
        zjjk_data = zjjk_data.mid(0,index + 1);
    }
    emit send_zjjk_reply(zjjk_data);

#else
    //定义请求信息
        QNetworkRequest zjjk_request;
        QNetworkReply * zjjk_reply;
        zjjk_request.setUrl(QUrl(JHPT_GET_DATA_URL));
        zjjk_request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded; charset=UTF-8");
        zjjk_request.setRawHeader(QByteArray("Accept"),QByteArray("application/json;charset=utf-8"));
        zjjk_request.setHeader(QNetworkRequest::CookieHeader,cookies);
        zjjk_reply = m_request_manager->post(zjjk_request,userInfo.toUtf8());

        //等待验证码返回信息
        QEventLoop request_loop;
        connect(zjjk_reply,&QNetworkReply::finished,&request_loop,&QEventLoop::quit);
        request_loop.exec();

        zjjk_data = zjjk_reply->readAll();
        emit send_zjjk_reply(zjjk_data);
        emit send_log(zjjk_data);

        zjjk_reply->deleteLater();
        zjjk_reply = nullptr;


#endif

}

//获取交互信息数据
void tbWorker::get_ask_data()
{
    //登录
    m_login();

    //整理请求POST数据
    std::string post_data = "orgType=3&sign=F";

    //清除结果数据
    ask_data.clear();


#ifndef _WIN32

    //通过CURL请求数据
    struct curl_slist * headers = NULL;
    headers = curl_slist_append(headers,"Accept:application/json;charset=utf-8");
    headers = curl_slist_append(headers,"Content-Type:application/x-www-form-urlencoded;charset=UTF-8");
    headers = curl_slist_append(headers,"User-Agent:Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0");
    CURL* curl = curl_easy_init();
    curl_easy_setopt(curl,CURLOPT_URL,"http://www.sipf.com.cn/jhpt/AskAnswer/getBianhao.action");
    curl_easy_setopt(curl,CURLOPT_POST,1L);
    curl_easy_setopt(curl,CURLOPT_POSTFIELDS,post_data.c_str());
    curl_easy_setopt(curl,CURLOPT_COOKIEFILE,"cookies");
    curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers);
    curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,request_callback);
    curl_easy_setopt(curl,CURLOPT_WRITEDATA,&ask_data);

    CURLcode res = curl_easy_perform(curl);
    if (res != CURLE_OK)
    {
        emit send_log(QString("get ask data fail: %1\n").arg(curl_easy_strerror(res)));
    }
    curl_easy_cleanup(curl);
    emit send_log(ask_data);

#else
    //定义请求信息
    QNetworkRequest ask_request;
    QNetworkReply * ask_reply;

    ask_request.setUrl(QUrl(JHPT_ASK_URL));
    ask_request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded; charset=UTF-8");
    ask_request.setRawHeader(QByteArray("Accept"),QByteArray("application/json;charset=utf-8"));
    ask_request.setHeader(QNetworkRequest::CookieHeader,cookies);
    ask_reply = m_request_manager->post(ask_request,QString("orgType=3&sign=F").toUtf8());

    //等待验证码返回信息
    QEventLoop request_loop;
    connect(ask_reply,&QNetworkReply::finished,&request_loop,&QEventLoop::quit);
    request_loop.exec();

    ask_data = ask_reply->readAll();
    emit send_log(ask_data);

    ask_reply->deleteLater();
    ask_reply = nullptr;

#endif

}

//获取A13数据
void tbWorker::get_a13_data()
{
    //登录
    m_login();

    //整理请求POST数据
    std::string current_date = m_busidate->getCheckDate().toStdString();
    std::string post_data = "message:{\"startDate\":\"";
    post_data.append(current_date);
    post_data.append("\"}");

    //清除结果数据
    a13_data.clear();

#ifndef _WIN32

    //通过CURL请求数据
    struct curl_slist * headers = NULL;
    headers = curl_slist_append(headers,"Accept:application/json;charset=utf-8");
    headers = curl_slist_append(headers,"Content-Type:application/x-www-form-urlencoded;charset=UTF-8");
    headers = curl_slist_append(headers,"User-Agent:Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0");
    CURL* curl = curl_easy_init();
    curl_easy_setopt(curl,CURLOPT_URL,"http://www.sipf.com.cn/jhpt/FileDealMan/getGridGl.action");
    curl_easy_setopt(curl,CURLOPT_POST,1L);
    curl_easy_setopt(curl,CURLOPT_POSTFIELDS,post_data.c_str());
    curl_easy_setopt(curl,CURLOPT_COOKIEFILE,"cookies");
    curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers);
    curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,request_callback);
    curl_easy_setopt(curl,CURLOPT_WRITEDATA,&a13_data);

    CURLcode res = curl_easy_perform(curl);
    if (res != CURLE_OK)
    {
        emit send_log(QString("get a13 data fail: %1\n").arg(curl_easy_strerror(res)));
    }
    curl_easy_cleanup(curl);
    emit send_log(a13_data);

#else

    //定义请求信息
    QNetworkRequest a13_request;
    QNetworkReply * a13_reply;

    a13_request.setUrl(QUrl(JHPT_A13_DATA_URL));
    a13_request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded; charset=UTF-8");
    a13_request.setRawHeader(QByteArray("Accept"),QByteArray("application/json;charset=utf-8"));
    a13_request.setHeader(QNetworkRequest::CookieHeader,cookies);
    a13_reply = m_request_manager->post(a13_request,QString::fromStdString(post_data).toUtf8());

    //等待验证码返回信息
    QEventLoop request_loop;
    connect(a13_reply,&QNetworkReply::finished,&request_loop,&QEventLoop::quit);
    request_loop.exec();

    a13_data = a13_reply->readAll();
    emit send_log(a13_data);

    a13_reply->deleteLater();
    a13_reply = nullptr;

#endif

}

//获取通知信息数据
void tbWorker::get_note_data()
{
    //清除结果数据
    note_data.clear();

    //通过CURL请求数据
    //定义请求信息
    QNetworkRequest note_request;
    QNetworkReply * note_reply;

    note_request.setUrl(QUrl(JHPT_NOTE_URL));
    note_reply = m_request_manager->get(note_request);

    //等待验证码返回信息
    QEventLoop request_loop;
    connect(note_reply,&QNetworkReply::finished,&request_loop,&QEventLoop::quit);
    request_loop.exec();

    note_data = note_reply->readAll();
    QString note_string = QString(note_data).remove(QRegExp("\\s"));
    note_data = note_string.toUtf8();

    emit send_log(note_data);

}

//执行检查
void tbWorker::check()
{
    //检查是否为交易日
    if(!m_busidate->isBusiDate())
    {
        emit send_log("当前日期为非交易日，不执行任何操作");
        return;
    }

    //执行ZJJK检查
    zjjk_check();

    //执行ASK检查
    ask_check();

    //执行A13检查
    a13_check();

    //执行通知检查
    note_check();

}

//执行核实反馈检查
void tbWorker::zjjk_check()
{
    int current_hour = QTime::currentTime().hour();
    int current_minute = QTime::currentTime().minute();

    //8点和16点执行监控，否则不执行
    if(current_hour != 16 && current_hour != 8)
    {
        return;
    }

    QList<int> check_minute = {0,10,20,30};

    if((current_hour == 8 && current_minute == 50) ||
       (current_hour == 16 && check_minute.contains(current_minute)))
    {
        //获取数据
        get_zjjk_data();

        //默认全部处理完成
        is_zjjk_success = true;

        //数据解析
        QJsonDocument zjjk_back_json = QJsonDocument::fromJson(zjjk_data);
        if(zjjk_back_json.isNull())
        {
            emit send_log("zjjk QJsonDocument数据解析失败");
            return;
        }

        QJsonArray zjjk_back_array = zjjk_back_json.array();
        for(int i = 0; i<zjjk_back_array.size(); i++)
        {
            auto dhs_num = zjjk_back_array[i].toVariant().toMap()["NUM_DHS"].toInt();
            auto zhs_num = zjjk_back_array[i].toVariant().toMap()["NUM_ZHS"].toInt();
            auto title_string = zjjk_back_array[i].toVariant().toMap()["TABLE_DESC"].toString();
            if(dhs_num > 0)
            {
                is_zjjk_success = false;
                emit send_log(QString("%1待核实数据：%2").arg(title_string,dhs_num));
            }
            if(zhs_num > 0)
            {
                is_zjjk_success = false;
                emit send_log(QString("%1再核实数据：%2").arg(title_string,zhs_num));
            }

        }

        if(!is_zjjk_success)
        {
            play_sound("audio/dhs3.wav");
            return;
        }

        if(current_minute == 30 && is_zjjk_success)
        {
            play_sound("audio/tbjkfk.wav");
            return;
        }
    }
}

//执行信息交互检查
void tbWorker::ask_check()
{
    int current_hour = QTime::currentTime().hour();
    int current_minute = QTime::currentTime().minute();
    QList<int> check_minute = {45,50};
    if(current_hour == 16 && check_minute.contains(current_minute))
    {
        get_ask_data();

    }else
    {
        return;
    }

    QString current_date = QDate::currentDate().toString("yyyy-MM-dd");
    if(QString(ask_data).contains(current_date))
    {
        play_sound("audio/xxjh.wav");
    }
}

//执行A13检查
void tbWorker::a13_check()
{
    int currentHour = QTime::currentTime().hour();
    int currentMinute = QTime::currentTime().minute();
    QList<int> check_minute = {0,10};
    if(currentHour == 11 && check_minute.contains(currentMinute))
    {
        get_a13_data();

    }else
    {
        return;
    }

    bool a13_success = false;

    //数据解析
    QJsonDocument a13_back_json = QJsonDocument::fromJson(a13_data);
    if(a13_back_json.isNull())
    {
        emit send_error("a13_data QJsonDocument数据解析失败");
        return;
    }

    QVariantMap a13_back_object = a13_back_json.object().toVariantMap();
    QVariantList a13_back_array = a13_back_object["rows"].toList();
    for(auto & item : a13_back_array)
    {
        QString FILE_CODE = item.toMap()["FILE_CODE"].toString();
        QString STATE = item.toMap()["STATE"].toString();
        if(FILE_CODE.contains("A13") && STATE.contains("处理成功"))
        {
            a13_success = true;
        }
    }

    if(!a13_success)
    {
        play_sound("audio/a13.wav");
    }
}

//执行通知检查
void tbWorker::note_check()
{
    int current_hour = QTime::currentTime().hour();
    int current_minute = QTime::currentTime().minute();
    QList<int> check_minute = {40,55};
    if(current_hour == 16 && check_minute.contains(current_minute))
    {
        get_note_data();

    }else
    {
        return;
    }

    QString current_date = QDate::currentDate().toString("yyyy-MM-dd");
    if(QString(note_data).contains(current_date))
    {
        play_sound("audio/tbnote.wav");
    }
}

//获取验证码
void tbWorker::get_jcaptcha_code()
{
#ifndef _WIN32
    CURL * curl = curl_easy_init();
    if(curl==NULL)
    {
        std::cout<< "curl init fail"<< std::endl;
        emit send_log("get_jcaptcha_code curl init fail");
        return ;
    }

    jcaptcha_code.clear();

    //请求数据
    curl_easy_setopt(curl,CURLOPT_URL,"http://www.sipf.com.cn/jhpt/jcaptcha");
    curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,jcaptcha_callback);
    curl_easy_setopt(curl,CURLOPT_WRITEDATA,&jcaptcha_code);
    curl_easy_setopt(curl,CURLOPT_COOKIEJAR,"cookies");
    CURLcode res = curl_easy_perform(curl);
    if (res != CURLE_OK)
    {
        curl_easy_cleanup(curl);
        emit send_log(QString("get jcaptcha fail: %1\n").arg(curl_easy_strerror(res)));
        return;
    }
    curl_easy_cleanup(curl);

    jcaptcha_code = jcaptcha_code.trimmed();

    emit send_log(QString("验证码：%1").arg(jcaptcha_code));
    qDebug()<< "验证码："<< jcaptcha_code << endl;
#else
    QNetworkRequest jcaptcha_request;
    jcaptcha_request.setUrl(QUrl(JHPT_VER_CODE_URL));
    QNetworkReply * jcaptcha_response = m_request_manager->get(jcaptcha_request);

    //等待验证码返回信息
    QEventLoop request_loop;
    connect(jcaptcha_response,&QNetworkReply::finished,&request_loop,&QEventLoop::quit);
    request_loop.exec();

    setlocale(LC_ALL, "C");
    tesseract::TessBaseAPI * api = new tesseract::TessBaseAPI();
    if(api->Init("./assets","eng"))
    {
        emit send_log("could not initialize apt");
        return;
    }
    QByteArray jcaptcha_byte = jcaptcha_response->readAll();
    const unsigned char* img = reinterpret_cast<const unsigned char*>(jcaptcha_byte.data());
    Pix * image = pixReadMem(img,jcaptcha_byte.length());
    api->SetImage(image);
    char * outText = api->GetUTF8Text();

    jcaptcha_code.clear();
    jcaptcha_code.append(outText);
    jcaptcha_code = jcaptcha_code.trimmed();
    emit send_log(QString("验证码：%1").arg(jcaptcha_code));

    api->End();
    delete[] outText;
    pixDestroy(&image);
    delete api;

    QList<QNetworkCookie> list_cookies = m_request_manager->cookieJar()->cookiesForUrl(QUrl(JHPT_VER_CODE_URL));
    this->cookies.setValue(list_cookies);

    jcaptcha_response->deleteLater();
    jcaptcha_response = nullptr;

#endif
}

//获取账号ascii码
void tbWorker::get_zhname_code()
{
    std::string name = USER_NAME.toStdString();
    std::string res;
    for(char item : name)
    {
        int item_int = (int)item;
        res.append(std::to_string(item_int));
        res.append(",");
    }
    res.pop_back();

    name_ascii.clear();
    name_ascii.push_back(QString::fromStdString(res));
}

//登录函数
void tbWorker::login()
{
    //获取验证码
    get_jcaptcha_code();

    //获取用户名ascii码
    get_zhname_code();

    QString USERNAME = USER_NAME;
    QString PASSWORD = PASS_WOERD;
    QByteArray NAMEPASSWORDMd5 = QCryptographicHash::hash(PASSWORD.toUtf8(),QCryptographicHash::Md5).toHex();
    NAMEPASSWORDMd5.append(USERNAME.toUtf8());
    NAMEPASSWORDMd5 = QCryptographicHash::hash(NAMEPASSWORDMd5,QCryptographicHash::Md5).toHex();
    QByteArray swlBa;
    swlBa.append(NAMEPASSWORDMd5);
    swlBa.append(jcaptcha_code.trimmed());
    swlBa = QCryptographicHash::hash(swlBa,QCryptographicHash::Md5).toHex();
    QString postString = QString("m=login&lm=%1&swl=%2&jcaptchacode=%3")
            .arg(name_ascii,QString(swlBa),jcaptcha_code.trimmed());
    QByteArray postDataByteArray = postString.toUtf8();
    std::string post_data = postDataByteArray.toStdString();


    //清除结果数据
    login_result.clear();

#ifndef _WIN32

    //开始数据请求
    CURL * curl = curl_easy_init();
    if(curl==NULL)
    {
        std::cout<< "curl init fail"<< std::endl;
        return ;
    }
    curl_easy_setopt(curl,CURLOPT_POST,1L);
    curl_easy_setopt(curl,CURLOPT_POSTFIELDS,post_data.c_str());
    curl_easy_setopt(curl,CURLOPT_URL,"http://www.sipf.com.cn/jhpt/security/security.jsp");
    curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,request_callback);
    curl_easy_setopt(curl,CURLOPT_WRITEDATA,&login_result);
    curl_easy_setopt(curl,CURLOPT_COOKIEFILE,"cookies");
    CURLcode res = curl_easy_perform(curl);
    if (res != CURLE_OK)
    {
        emit send_log(QString("login fail: %1\n").arg(curl_easy_strerror(res)));
    }
    curl_easy_cleanup(curl);
    login_result = login_result.trimmed();
    qDebug()<< "login_result:" << login_result.trimmed() <<endl;

#else
    QNetworkRequest login_request;
    QNetworkReply * login_reply;
    login_request.setUrl(JHPT_LOGIN_URL);
    login_request.setHeader(QNetworkRequest::CookieHeader,cookies);
    login_request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded; charset=UTF-8");


    login_reply = m_request_manager->post(login_request,postDataByteArray);
    //等待验证码返回信息
    QEventLoop request_loop;
    connect(login_reply,&QNetworkReply::finished,&request_loop,&QEventLoop::quit);
    request_loop.exec();

    login_result = login_reply->readAll();
    login_result = login_result.trimmed();

    emit send_log(QString("login_result: %1").arg(QString(login_result)));

    login_reply->deleteLater();
    login_reply = nullptr;

#endif

}

//登录函数
void tbWorker::m_login()
{
    login();

    while (true) {

        if(login_result.contains("true"))
        {
            emit send_log("login success");
            return;
        }else
        {
            emit send_log("login fail");
            QThread::sleep(5);
            login();
        }

    }
}

//提示音播放
void tbWorker::play_sound(const QString &path)
{
    QString audio_path = QDir::current().filePath(path);

#ifdef _WIN32

    BOOL res = PlaySound(audio_path.toStdWString().c_str(),GetModuleHandle(NULL), SND_FILENAME | SND_ASYNC);
    if(res == TRUE)
    {
        emit send_log(QString("完成%1的播放").arg(path));
    }else
    {
        emit send_error(QString("语音提醒发生错误，错误"));
    }

#else
    auto player = new QMediaPlayer;
    player->setMedia(QMediaContent(QUrl::fromLocalFile(audio_path)));
    player->play();

    //语音播放错误时发送错误信息
    if(player->error() != QMediaPlayer::NoError)
    {
        emit send_error(QString("语音提醒发生错误，错误：%1").arg(player->errorString()));
    }else
    {
       emit send_log(QString("完成%1的播放").arg(path));
    }
    //释放资源
    delete player;
#endif

}

